package com.isoft.utils;

import com.isoft.entity.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * XML解析工具类
 * 支持BASE和DFME所有类型的XML数据解析
 */
public class XmlParseUtil {

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     * 解析结果封装类
     */
    public static class ParseResult {
        private MsgMeta msgMeta;
        private AirportInfo airportInfo;
        private FlightDynamic flightDynamic;
        private List<GateAssignment> gateAssignments;
        private List<StandAssignment> standAssignments;
        private List<BeltAssignment> beltAssignments;
        private FlightBase flightBase;
        private List<CheckinDisplay> checkinDisplays;

        // 构造方法
        public ParseResult() {
            this.gateAssignments = new ArrayList<>();
            this.standAssignments = new ArrayList<>();
            this.beltAssignments = new ArrayList<>();
            this.checkinDisplays = new ArrayList<>();
        }

        // Getters and Setters
        public MsgMeta getMsgMeta() { return msgMeta; }
        public void setMsgMeta(MsgMeta msgMeta) { this.msgMeta = msgMeta; }

        public AirportInfo getAirportInfo() { return airportInfo; }
        public void setAirportInfo(AirportInfo airportInfo) { this.airportInfo = airportInfo; }

        public FlightDynamic getFlightDynamic() { return flightDynamic; }
        public void setFlightDynamic(FlightDynamic flightDynamic) { this.flightDynamic = flightDynamic; }

        public List<GateAssignment> getGateAssignments() { return gateAssignments; }
        public void setGateAssignments(List<GateAssignment> gateAssignments) { this.gateAssignments = gateAssignments; }

        public List<StandAssignment> getStandAssignments() { return standAssignments; }
        public void setStandAssignments(List<StandAssignment> standAssignments) { this.standAssignments = standAssignments; }

        public List<BeltAssignment> getBeltAssignments() { return beltAssignments; }
        public void setBeltAssignments(List<BeltAssignment> beltAssignments) { this.beltAssignments = beltAssignments; }

        public FlightBase getFlightBase() { return flightBase; }
        public void setFlightBase(FlightBase flightBase) { this.flightBase = flightBase; }

        public List<CheckinDisplay> getCheckinDisplays() { return checkinDisplays; }
        public void setCheckinDisplays(List<CheckinDisplay> checkinDisplays) { this.checkinDisplays = checkinDisplays; }
    }

    /**
     * 解析单个XML文件
     */
    public static ParseResult parseXmlFile(File xmlFile) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(xmlFile);
        Element root = document.getRootElement();

        ParseResult result = new ParseResult();

        // 解析META信息
        Element metaElement = root.element("META");
        if (metaElement != null) {
            MsgMeta msgMeta = parseMsgMeta(metaElement);
            result.setMsgMeta(msgMeta);

            // 根据消息类型进行不同的解析
            String type = msgMeta.getType();
            String styp = msgMeta.getStyp();

            if ("BASE".equals(type) && "APUE".equals(styp)) {
                // 解析机场基础信息
                Element apotElement = root.element("APOT");
                if (apotElement != null) {
                    AirportInfo airportInfo = parseAirportInfo(apotElement, xmlFile.getName());
                    result.setAirportInfo(airportInfo);
                }
            } else if ("DFME".equals(type)) {
                // 解析航班动态信息
                Element dfltElement = root.element("DFLT");
                if (dfltElement != null) {
                    // 为所有DFME类型创建FlightBase基础信息
                    FlightBase flightBase = parseFlightBase(dfltElement, xmlFile.getName());
                    result.setFlightBase(flightBase);

                    // 解析航班动态信息（仅对特定子类型）
                    if ("CFCE".equals(styp) || "BORE".equals(styp) || "DEPE".equals(styp) ||
                            "ARRE".equals(styp) || "FRTT".equals(styp) || "FETT".equals(styp) ||
                            "POKE".equals(styp) || "ONRE".equals(styp)) {
                        FlightDynamic flightDynamic = parseFlightDynamic(dfltElement, styp, xmlFile.getName());
                        result.setFlightDynamic(flightDynamic);
                    }

                    // 根据子类型解析资源分配信息
                    if ("GTLS".equals(styp)) {
                        // 解析登机门信息
                        List<GateAssignment> gates = parseGateAssignments(dfltElement, xmlFile.getName());
                        result.setGateAssignments(gates);
                    } else if ("STLS".equals(styp)) {
                        // 解析机位信息
                        List<StandAssignment> stands = parseStandAssignments(dfltElement, xmlFile.getName());
                        result.setStandAssignments(stands);
                    } else if ("BLLS".equals(styp)) {
                        // 解析行李转盘信息
                        List<BeltAssignment> belts = parseBeltAssignments(dfltElement, xmlFile.getName());
                        result.setBeltAssignments(belts);
                    } else if ("CKLS".equals(styp)) {
                        // 解析值机显示信息
                        List<CheckinDisplay> checkins = parseCheckinDisplays(dfltElement, xmlFile.getName());
                        result.setCheckinDisplays(checkins);
                    }
                }
            }
        }

        return result;
    }

    /**
     * 解析消息元数据
     */
    private static MsgMeta parseMsgMeta(Element metaElement) {
        MsgMeta msgMeta = new MsgMeta();
        msgMeta.setSndr(getElementText(metaElement, "SNDR"));
        msgMeta.setRcvr(getElementText(metaElement, "RCVR"));
        msgMeta.setSeqn(getElementText(metaElement, "SEQN"));
        msgMeta.setDttm(getElementText(metaElement, "DTTM"));
        msgMeta.setType(getElementText(metaElement, "TYPE"));
        msgMeta.setStyp(getElementText(metaElement, "STYP"));
        msgMeta.setSourceFile(getElementText(metaElement, "SOURCE_FILE"));
        return msgMeta;
    }

    /**
     * 解析机场基础信息
     */
    private static AirportInfo parseAirportInfo(Element apotElement, String sourceFile) {
        AirportInfo airportInfo = new AirportInfo();
        airportInfo.setCode(getElementText(apotElement, "CODE"));
        airportInfo.setFrcd(getElementText(apotElement, "FRCD"));
        airportInfo.setApat(getElementText(apotElement, "APAT"));
        airportInfo.setCnnm(getElementText(apotElement, "CNNM"));
        airportInfo.setEnnm(getElementText(apotElement, "ENNM"));
        airportInfo.setAiso(getElementText(apotElement, "AISO"));
        airportInfo.setApsn(getElementText(apotElement, "APSN"));
        airportInfo.setSourceFile(sourceFile);
        return airportInfo;
    }

    /**
     * 解析航班动态信息
     */
    private static FlightDynamic parseFlightDynamic(Element dfltElement, String styp, String sourceFile) {
        FlightDynamic flightDynamic = new FlightDynamic();

        // 基础信息
        flightDynamic.setFlid(getElementTextAsLong(dfltElement, "FLID"));
        flightDynamic.setFfid(getElementText(dfltElement, "FFID"));
        flightDynamic.setFide(getElementText(dfltElement, "FIDE"));
        flightDynamic.setFatt(getElementText(dfltElement, "FATT"));

        // 根据子类型解析不同的字段
        switch (styp) {
            case "BORE":
                flightDynamic.setStat(getElementText(dfltElement, "STAT"));
                flightDynamic.setIsta(getElementText(dfltElement, "ISTA"));
                flightDynamic.setBort(parseDateTime(getElementText(dfltElement, "BORT")));
                flightDynamic.setMsta(getElementText(dfltElement, "MSTA"));
                flightDynamic.setMist(getElementText(dfltElement, "MIST"));
                flightDynamic.setMbor(parseDateTime(getElementText(dfltElement, "MBOR")));
                break;
            case "DEPE":
                flightDynamic.setDepe(parseDateTime(getElementText(dfltElement, "DEPE")));
                break;
            case "ARRE":
                flightDynamic.setArre(parseDateTime(getElementText(dfltElement, "ARRE")));
                break;
            case "FRTT":
                flightDynamic.setFrtt(parseDateTime(getElementText(dfltElement, "FRTT")));
                break;
            case "FETT":
                flightDynamic.setFett(parseDateTime(getElementText(dfltElement, "FETT")));
                break;
            case "POKE":
                flightDynamic.setPoke(parseDateTime(getElementText(dfltElement, "POKE")));
                break;
            case "ONRE":
                flightDynamic.setOnre(parseDateTime(getElementText(dfltElement, "ONRE")));
                break;
            case "CFCE":
                flightDynamic.setCfce(getElementText(dfltElement, "CFCE"));
                break;
        }

        flightDynamic.setSourceFile(sourceFile);
        return flightDynamic;
    }

    /**
     * 解析登机门分配信息
     */
    private static List<GateAssignment> parseGateAssignments(Element dfltElement, String sourceFile) {
        List<GateAssignment> assignments = new ArrayList<>();
        Element gtlsElement = dfltElement.element("GTLS");

        if (gtlsElement != null) {
            List<Element> gateElements = gtlsElement.elements("GATE");
            for (Element gateElement : gateElements) {
                GateAssignment assignment = new GateAssignment();
                assignment.setFlid(getElementTextAsLong(dfltElement, "FLID"));
                assignment.setFfid(getElementText(dfltElement, "FFID"));
                assignment.setFide(getElementText(dfltElement, "FIDE"));
                assignment.setFatt(getElementText(dfltElement, "FATT"));

                assignment.setGtno(getElementTextAsInteger(gateElement, "GTNO"));
                assignment.setGateId(getElementText(gateElement, "ID"));
                assignment.setCode(getElementText(gateElement, "CODE"));
                assignment.setGtat(getElementText(gateElement, "GTAT"));
                assignment.setEstr(parseDateTime(getElementText(gateElement, "ESTR")));
                assignment.setEend(parseDateTime(getElementText(gateElement, "EEND")));
                assignment.setRstr(parseDateTime(getElementText(gateElement, "RSTR")));
                assignment.setRend(parseDateTime(getElementText(gateElement, "REND")));
                assignment.setBtsc(getElementText(gateElement, "BTSC"));
                assignment.setSourceFile(sourceFile);

                assignments.add(assignment);
            }
        }

        return assignments;
    }

    /**
     * 解析机位分配信息
     */
    private static List<StandAssignment> parseStandAssignments(Element dfltElement, String sourceFile) {
        List<StandAssignment> assignments = new ArrayList<>();
        Element stlsElement = dfltElement.element("STLS");

        if (stlsElement != null) {
            List<Element> standElements = stlsElement.elements("STND");
            for (Element standElement : standElements) {
                StandAssignment assignment = new StandAssignment();
                assignment.setFlid(getElementTextAsLong(dfltElement, "FLID"));
                assignment.setFfid(getElementText(dfltElement, "FFID"));
                assignment.setFide(getElementText(dfltElement, "FIDE"));
                assignment.setFatt(getElementText(dfltElement, "FATT"));

                assignment.setStno(getElementTextAsInteger(standElement, "STNO"));
                assignment.setCode(getElementText(standElement, "CODE"));
                assignment.setEstr(parseDateTime(getElementText(standElement, "ESTR")));
                assignment.setEend(parseDateTime(getElementText(standElement, "EEND")));
                assignment.setRstr(parseDateTime(getElementText(standElement, "RSTR")));
                assignment.setRend(parseDateTime(getElementText(standElement, "REND")));
                assignment.setCssi(getElementText(standElement, "CSSI"));
                assignment.setBtsc(getElementText(standElement, "BTSC"));
                assignment.setSourceFile(sourceFile);

                assignments.add(assignment);
            }
        }

        return assignments;
    }

    /**
     * 解析行李转盘分配信息
     */
    private static List<BeltAssignment> parseBeltAssignments(Element dfltElement, String sourceFile) {
        List<BeltAssignment> assignments = new ArrayList<>();
        Element bllsElement = dfltElement.element("BLLS");

        if (bllsElement != null) {
            List<Element> beltElements = bllsElement.elements("BELT");
            for (Element beltElement : beltElements) {
                BeltAssignment assignment = new BeltAssignment();
                assignment.setFlid(getElementTextAsLong(dfltElement, "FLID"));
                assignment.setFfid(getElementText(dfltElement, "FFID"));
                assignment.setFide(getElementText(dfltElement, "FIDE"));
                assignment.setFatt(getElementText(dfltElement, "FATT"));

                assignment.setBtno(getElementTextAsInteger(beltElement, "BTNO"));
                assignment.setBeltId(getElementText(beltElement, "ID"));
                assignment.setCode(getElementText(beltElement, "CODE"));
                assignment.setBtat(getElementText(beltElement, "BTAT"));
                assignment.setEstr(parseDateTime(getElementText(beltElement, "ESTR")));
                assignment.setEend(parseDateTime(getElementText(beltElement, "EEND")));
                assignment.setRstr(parseDateTime(getElementText(beltElement, "RSTR")));
                assignment.setRend(parseDateTime(getElementText(beltElement, "REND")));
                assignment.setBtsc(getElementText(beltElement, "BTSC"));
                assignment.setSourceFile(sourceFile);

                assignments.add(assignment);
            }
        }

        return assignments;
    }

    /**
     * 获取元素文本值
     */
    private static String getElementText(Element parentElement, String elementName) {
        Element element = parentElement.element(elementName);
        return element != null ? element.getTextTrim() : null;
    }

    /**
     * 获取元素文本值并转换为Integer
     */
    private static Integer getElementTextAsInteger(Element parentElement, String elementName) {
        return getElementTextAsInteger(parentElement, elementName, null);
    }

    private static Integer getElementTextAsInteger(Element parentElement, String elementName, Integer defaultValue) {
        String text = getElementText(parentElement, elementName);
        if (text != null && !text.isEmpty()) {
            try {
                return Integer.parseInt(text);
            } catch (NumberFormatException e) {
                return defaultValue;
            }
        }
        return defaultValue;
    }

    /**
     * 获取元素文本值并转换为Long
     */
    private static Long getElementTextAsLong(Element parentElement, String elementName) {
        String text = getElementText(parentElement, elementName);
        if (text != null && !text.isEmpty()) {
            try {
                return Long.parseLong(text);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * 解析日期时间字符串
     */
    private static Date parseDateTime(String dateTimeStr) {
        if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
            return null;
        }
        try {
            return DATE_FORMAT.parse(dateTimeStr);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 解析航班基础信息
     */
    private static FlightBase parseFlightBase(Element dfltElement, String sourceFile) {
        FlightBase flightBase = new FlightBase();

        // 从DFLT元素解析基础航班信息
        String ffid = getElementText(dfltElement, "FFID");
        String fide = getElementText(dfltElement, "FIDE");

        // 解析航空公司代码和航班号
        if (ffid != null && ffid.contains("-")) {
            String[] parts = ffid.split("-");
            if (parts.length >= 2) {
                flightBase.setAirlineCode(parts[0]); // 航空公司代码
                flightBase.setFlightNumber(parts[1]); // 航班号
            }
        }

        // 解析执行日期
        if (ffid != null && ffid.contains("-") && ffid.split("-").length >= 3) {
            String[] parts = ffid.split("-");
            String dateStr = parts[2];
            if (dateStr.length() == 8) {
                try {
                    Date execDate = new SimpleDateFormat("yyyyMMdd").parse(dateStr);
                    flightBase.setFlightDate(execDate);
                } catch (ParseException e) {
                    // 解析失败时忽略
                }
            }
        }

        // 设置默认状态
        flightBase.setStatus("SCHEDULED");

        // 根据进出标志设置出发/到达机场
        if (ffid != null && ffid.endsWith("-D")) {
            // 出港航班，设置出发机场
            flightBase.setDepartureAirport("PEK"); // 默认机场，实际应从XML解析
        } else if (ffid != null && ffid.endsWith("-A")) {
            // 进港航班，设置到达机场
            flightBase.setArrivalAirport("PEK"); // 默认机场，实际应从XML解析
        }

        return flightBase;
    }

    /**
     * 解析值机显示信息
     */
    private static List<CheckinDisplay> parseCheckinDisplays(Element dfltElement, String sourceFile) {
        List<CheckinDisplay> displays = new ArrayList<>();
        Element cklsElement = dfltElement.element("CKLS");

        if (cklsElement != null) {
            List<Element> checkElements = cklsElement.elements("CHCK");
            for (Element checkElement : checkElements) {
                CheckinDisplay display = new CheckinDisplay();

                // 关联航班ID（从父元素获取）
                Long flightId = getElementTextAsLong(dfltElement, "FLID");
                display.setFLIGHT_ID(flightId);

                // 构建值机显示内容
                String fcdp = getElementText(checkElement, "FCDP");
                String mcdp = getElementText(checkElement, "MCDP");

                display.setFCDP(fcdp); // 值机柜台及区域显示1(国内/地区)
                display.setMCDP(mcdp); // 值机柜台及区域显示2(混合航班国际)

                displays.add(display);
            }
        }

        return displays;
    }

    /**
     * 批量解析文件夹中的所有XML文件
     */
    public static Map<String, ParseResult> parseXmlFolder(String xmlFolderPath) {
        Map<String, ParseResult> results = new HashMap<>();
        File folder = new File(xmlFolderPath);

        if (!folder.exists() || !folder.isDirectory()) {
            return results;
        }

        File[] xmlFiles = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".xml"));
        if (xmlFiles != null) {
            for (File xmlFile : xmlFiles) {
                try {
                    ParseResult result = parseXmlFile(xmlFile);
                    results.put(xmlFile.getName(), result);
                } catch (DocumentException e) {
                    System.err.println("解析文件失败: " + xmlFile.getName() + ", 错误: " + e.getMessage());
                }
            }
        }

        return results;
    }

    /**
     * 按消息类型过滤解析结果
     */
    public static Map<String, List<ParseResult>> groupResultsByMessageType(Map<String, ParseResult> results) {
        Map<String, List<ParseResult>> groupedResults = new HashMap<>();

        for (Map.Entry<String, ParseResult> entry : results.entrySet()) {
            ParseResult result = entry.getValue();
            if (result.getMsgMeta() != null) {
                String messageType = result.getMsgMeta().getType() + "-" + result.getMsgMeta().getStyp();
                groupedResults.computeIfAbsent(messageType, k -> new ArrayList<>()).add(result);
            }
        }

        return groupedResults;
    }
} 